let currentPath = ""; // 当前路径记录

let rootPath = "";
// 在全局或模块作用域中创建状态存储对象
let checkedState = {};

let checkFile = {};

let sessionControl = null;

let sessionDownload = null;

 // 初始化检查
 CheckAuth();

// 初始化加载根目录
window.onload = function () {
    // 全选功能实现
    document.getElementById('selectAll').addEventListener('change', function (e) {
        const checkboxes = document.querySelectorAll('.file-checkbox');
        checkboxes.forEach(checkbox => {
            checkbox.checked = e.target.checked;
            // 同步状态存储
            const storageKey = checkbox.dataset.storageKey;
            checkedState[storageKey] = e.target.checked;
        });
    });

    document.getElementById('selectAll').checked = false;

    const urlParams = new URLSearchParams(window.location.search);
        
        // 获取并显示版本信息
    document.getElementById('version-name').textContent = urlParams.get('name');
    document.getElementById('version-number').textContent = urlParams.get('version');
    document.getElementById('version-date').textContent = urlParams.get('created');
    document.getElementById('version-creator').textContent = urlParams.get('creator');
    document.getElementById('version-id').textContent = urlParams.get('id');

    currentPath = urlParams.get('id');
    rootPath = currentPath;

    loadDirectory(currentPath);
};

// 加载目录内容
async function loadDirectory(path) {
    try {
        // 遍历删除所有键
        Object.keys(checkedState).forEach(key => {
            delete checkedState[key];
        });

        Object.keys(checkFile).forEach(key => {
            delete checkFile[key];
        });

        currentPath = path; // 更新当前路径    

        const response = await fetch('/api/file/list', {
            method: 'POST',
            headers: {
              'Content-Type': 'application/json' // 声明 JSON 数据格式‌:ml-citation{ref="1,2" data="citationList"}
            },
            body: JSON.stringify({ // 序列化请求体‌:ml-citation{ref="1,3" data="citationList"}
              version_id: rootPath, // 需替换为实际版本ID
              path: path // 保持路径编码
            })
        });

        if (!response.ok) {
            throw new Error(`HTTP 错误! 状态码: ${response.status}`);
        } else {
            const data = await response.json();
            if (data == null) {
                toggleBackButton(path);
            } else {
                //renderFileList(data, path);
                renderFileListEx(data);
            }

            updatePath(currentPath)
        }
    } catch (error) {
        console.error('请求失败:', error);
        throw error; // 继续向上抛出错误
    }
}

// 通用创建按钮函数
function createButton(iconClass, btnClass, clickHandler) {
    const btn = document.createElement('button');
    btn.className = `action-btn ${btnClass}`;

    const icon = document.createElement('i');
    icon.className = iconClass;
    btn.appendChild(icon);

    btn.addEventListener('click', clickHandler);
    return btn;
}

// 渲染文件列表
function renderFileListEx(files) {
    const tbody = document.getElementById('file-list-body');
    tbody.innerHTML = ''; // 清空旧内容    


    if (currentPath != '' && currentPath != 'FileList' && currentPath != rootPath && currentPath != "FileList/" + rootPath) {
        const rowBack = document.createElement("tr");
        rowBack.className = "file-row";
        // +++ 新增固定按钮列 +++
        const fixedCell = document.createElement("td");
        const itemback = document.createElement("button");
        itemback.className = 'back-btn'
        itemback.textContent = '...'
        itemback.addEventListener("click", () => {
            goBack();
        });
        fixedCell.appendChild(itemback);
        rowBack.appendChild(fixedCell); // 作为第一列插入
        tbody.appendChild(rowBack);
    }

    files.forEach(file => {
        const row = document.createElement("tr");
        row.className = "file-row";

        // 复选框列
        const checkboxCell = document.createElement("td");
        const checkboxContainer = document.createElement("div");
        checkboxContainer.className = "checkbox-container";

        // 复选框生成逻辑（保持原有代码）
        const checkbox = document.createElement("input");
        checkbox.type = "checkbox";
        checkbox.className = "file-checkbox";
        const storageKey = file.path.replace(/\//g, '_');
        checkbox.dataset.storageKey = storageKey;
        checkbox.checked = false;
        checkFile[storageKey] = file;
        checkbox.addEventListener('change', (e) => {
            checkedState[storageKey] = e.target.checked;
            console.info("file:", checkFile[storageKey].name)
        });

        checkboxContainer.appendChild(checkbox);
        checkboxCell.appendChild(checkboxContainer);
        checkboxCell.className = "checkbox-column"; // 应用预定义的CSS类
        row.appendChild(checkboxCell);

        // 文件名列
        const nameCell = document.createElement("td");
        const nameContainer = document.createElement("div");
        nameContainer.style.display = "flex";
        nameContainer.style.alignItems = "center";

        // 图标与名称
        const icon = document.createElement("span");
        icon.className = file.isDir ? "icon-folder" : "icon-file";
        icon.textContent = file.isDir ? "📁 " : "📄 ";

        const nameSpan = document.createElement("span");
        nameSpan.textContent = file.name;
        nameSpan.style.marginLeft = "8px";
        nameSpan.style.cursor = "pointer";

        // 保持原有点击逻辑
        if (file.isDir) {
            nameSpan.addEventListener("click", () => loadDirectory(file.path + file.name));
        } else {
            //nameSpan.addEventListener("click", () => handleFileClick(file));
        }

        nameContainer.appendChild(icon);
        nameContainer.appendChild(nameSpan);
        nameCell.appendChild(nameContainer);
        nameCell.className = "filename-column"; // 应用预定义的CSS类
        row.appendChild(nameCell);

        // 操作按钮列
        const createActionCell = (buttons) => {
            const cell = document.createElement("td");
            cell.className = "action-column";
            buttons.forEach(btn => cell.appendChild(btn));
            return cell;
        };

        // 创建删除按钮
        const deleteBtn = createButton(
            'fas fa-trash',
            'trash-btn',
            async () => { // 关键点1：将回调改为 async 函数
                try {
                    await deleteSelf(file); // 关键点2：等待异步操作完成
                    await loadDirectory(currentPath);
                } catch (error) {
                    console.error('删除失败:', error);
                    // 可添加错误提示逻辑，例如：
                    // showErrorToast('文件删除失败');
                }
            }
        );

        // 创建重命名按钮
        const renameBtn = createButton(
            'fas fa-pen',  // 铅笔图标
            'rename-btn',
            async () => {
                const newName = prompt('请输入新名称：');
                if (newName) {
                    const renameResult = await renameFile(file.path, newName);
                    if (renameResult.success) {
                        loadDirectory(currentPath);
                    } else {
                        alert(`操作失败: ${renameResult.error}`);
                    }
                }
            }
        );

        const deleteCloum = createActionCell([deleteBtn]);
        deleteCloum.className = "action-column-del";
        const renameCloum = createActionCell([renameBtn]);
        renameCloum.className = "action-column-rename";

        // 添加操作列
        row.appendChild(deleteCloum);
        row.appendChild(renameCloum);

        tbody.appendChild(row);
    });
}

function handleFileClick(file) {
    //console.log("文件点击预留事件", file);  // 待实现具体逻辑‌:ml-citation{ref="1,3" data="citationList"}
    downloadEntireFile(file)
}

// 展开/折叠文件夹
function toggleFolder(element) {
    const path = element.dataset.path;
    currentPath = path;
    toggleBackButton(path);

    const children = element.querySelector("ul");
    if (children) {  // 已展开则折叠
        element.removeChild(children);
    } else {         // 未展开则加载
        loadDirectory(path);
    }
}

function getParentDirectory(path) {
    // 统一替换所有反斜杠为正斜杠（兼容 Windows 路径）
    const normalizedPath = path.replace(/\\/g, '/');
    
    // 分割路径并过滤空段（处理多余斜杠）
    const segments = normalizedPath.split('/').filter(segment => segment !== '');
    
    // 移除最后一个路径段（如果存在）
    if (segments.length > 1) {
        segments.pop();
        return segments.join('/'); // 重新拼接路径
    }
    
    // 根目录或无父目录时返回 null
    return null; 
}

function goBack() {

    //lastPath = currentPath.split("\\").slice(0, -1).join("\\");
    lastPath = getParentDirectory(currentPath);
    loadDirectory(lastPath);
}

async function deleteSelf(file) {
    const response = await fetch(`/api/file/delete`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ path: file.path, name: file.name,  version:rootPath, isDir: file.isDir})
    })

    if (!response.ok) {
        alert(`删除失败,接口调用失败`)
    } else {
        return response;
    }
}

function toggleBackButton(path) {
    const tbody = document.getElementById('file-list-body');
    tbody.innerHTML = ''; // 清空旧内容    


    if (currentPath != '' && currentPath != 'FileList' && currentPath != rootPath && currentPath != "FileList/" + rootPath) {
        const rowBack = document.createElement("tr");
        rowBack.className = "file-row";
        // +++ 新增固定按钮列 +++
        const fixedCell = document.createElement("td");
        const itemback = document.createElement("button");
        itemback.className = 'back-btn'
        itemback.textContent = '...'
        itemback.addEventListener("click", () => {
            goBack();
        });
        fixedCell.appendChild(itemback);
        rowBack.appendChild(fixedCell); // 作为第一列插入
        tbody.appendChild(rowBack);
    }
}

// 下载文件
async function downloadFile(file) {
    const fileName = file.name;  // 目标文件名
    const chunkSize = 1024 * 1024;     // 分片大小（1MB）
    let currentChunk = 0;
    let totalChunks = 0;
    let fileBlobs = [];

    // 获取文件总大小
    const response = await fetch('/api/download', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ "method": "getSize", path: file.path, name: fileName })  // 路径与文件名分离传输‌:ml-citation{ref="1,5" data="citationList"}
    });

    if (!response.ok) {
        throw new Error(`HTTP error! Status: ${response.status}`);
    }

    const data = await response.json();
    console.log('Server response:', data);

    const totalSize = parseInt(data.fileSize, 10);
    totalChunks = Math.ceil(totalSize / chunkSize);

    // 分片下载循环
    while (currentChunk < totalChunks) {
        const start = currentChunk * chunkSize;
        const end = Math.min(start + chunkSize - 1, totalSize - 1);

        const chunkResponse = await fetch('/api/download', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                'Range': `bytes=${start}-${end}`  // 保持范围头‌:ml-citation{ref="1,6" data="citationList"}
            },
            body: JSON.stringify({ path: file.path, name: fileName })
        });

        if (chunkResponse.status === 206) {  // 分片成功‌:ml-citation{ref="3" data="citationList"}
            const blob = await chunkResponse.blob();
            fileBlobs.push(blob);
            currentChunk++;
            console.log(`已下载分片 ${currentChunk}/${totalChunks}`);
        } else {
            console.error("分片下载失败");
            break;
        }
    }

    // 合并分片并触发下载
    const fullBlob = new Blob(fileBlobs);
    const downloadUrl = window.URL.createObjectURL(fullBlob);
    const link = document.createElement('a');
    link.href = downloadUrl;
    link.download = fileName;
    link.click();
    window.URL.revokeObjectURL(downloadUrl);
}


// 生成UUID函数
function generateUUID() {
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
        const r = Math.random() * 16 | 0;
        return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16);
    });
}


// 显示错误
function showUploadError(message) {
    const errorDiv = document.createElement('div');
    errorDiv.className = 'error-message';
    errorDiv.textContent = message;

    const modalContent = document.querySelector('.modal-content');
    modalContent.appendChild(errorDiv);

    setTimeout(() => errorDiv.remove(), 3000);
}


function uploadFile() {
    const input = document.createElement('input');
    input.type = 'file';
    input.hidden = true;
    input.multiple = true;
    input.webkitdirectory = false;
    input.addEventListener('change', async e => {
        const files = e.target.files;
        if (!files.length) return;


        try {
            chunkedUploadEx(files);
        } catch (error) {
            console.error('上传流程中断:', error);
            alert(`上传失败: ${error.message}`);
        }
    });
    document.body.appendChild(input);
    input.click();
    input.remove();
}


async function renameFile(oldPath, newFileName) {
    try {
        const response = await fetch('/api/file/rename', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                // 如果需要认证可添加
                // 'Authorization': `Bearer ${token}`
            },
            body: JSON.stringify({
                old_path: oldPath,
                new_name: newFileName
            })
        });

        // 首先检查HTTP状态
        if (!response.ok) {
            throw new Error(`HTTP错误 ${response.status}`);
        }

        const result = await response.json();

        // 根据Beego的响应格式处理
        if (result.code === "0") {
            console.log('重命名成功');
            //alert('重命名成功');
            return {
                success: true,
                error: ''
            };
        } else {
            throw new Error(result.message || '未知错误');
        }
    } catch (error) {
        console.error('重命名失败:', error);
        return {
            success: false,
            error: error.message || '请求发送失败'
        };
    }
}

// 上传管理器
class SessionManager {
    Uploads;
    Downloads;
    _cancelHandlerBound;

    constructor() {
        this.Uploads = new Map();
        this.Downloads = new Map();
        this._cancelHandlerBound = false; // 事件委托标记
    }

    addUpload(file, chunkSize = 5 * 1024 * 1024) {
        const uploadId = generateUUID();

        //this.Uploads = new Map();

        this.Uploads.set(uploadId, {
            file,
            progress: 0,
            chunksDone: 0,
            totalChunks: Math.ceil(file.size / chunkSize),
            controller: new AbortController(),
            status: 'pending'
        });

        this.updateUI();
        this.startUpload(uploadId, chunkSize);
    }


    addDownload(file) {
        const DownloadId = generateUUID();

        //this.Downloads = new Map();

        this.Downloads.set(DownloadId, {
            file,
            progress: 0,
            chunksDone: 0,
            status: 'pending'
        });

        this.updateDownloadUI();

        const data = this.Downloads.get(DownloadId);
        if (!data) {
            console.error("upload data missing:", DownloadId);
            isProcessing = false;
            return;
        }

        this.downloadWithProgress(DownloadId, data.file.path, data.file.name);
    }


    async startUpload(uploadId, chunkSize) {

        const data = this.Uploads.get(uploadId);

        if (!data) {
            console.error("upload data missing:", uploadId);
            isProcessing = false;
            return;
        }

        try {

            data.status = 'uploading';

            const { file, totalChunks, controller } = data;

            for (let index = 0; index < totalChunks; index++) {
                // 每次循环前重新获取最新状态
                const currentData = this.Uploads.get(uploadId);
                if (!currentData || controller.signal.aborted) break;

                // 上传分片逻辑...
                await uploadChunk(data.file, index, uploadId, data.totalChunks, chunkSize);

                let filePathIndex = joinAndNormalizePath(currentPath, data.file.webkitRelativePath);
                if(data.file.webkitRelativePath.length == 0){
                    filePathIndex = joinAndNormalizePath(currentPath, data.file.name);
                }
                

                if (index === totalChunks - 1) {
                    const mergePayload = {
                        uploadId,
                        filename: data.file.name,
                        filePath: filePathIndex,
                        currentPath: currentPath,
                        version: rootPath
                    };

                    const mergeRes = await fetch('/api/upload/merge', {
                        method: 'POST',
                        headers: { 'Content-Type': 'application/json' },
                        body: JSON.stringify(mergePayload)
                    });

                    // 重命名响应数据变量
                    const responseData = await mergeRes.json();
                    if (responseData.code === "0") {
                        console.log('合并成功');
                        //data.status = 'completed';
                        // 原子化更新
                        this.Uploads.set(uploadId, {
                            ...currentData,
                            progress: 100,
                            chunksDone: index + 1,
                            status: 'completed'
                        });
                    } else {
                        console.error('合并失败:', responseData.message);
                        //data.status = 'error';
                        // 原子化更新
                        this.Uploads.set(uploadId, {
                            ...currentData,
                            status: 'error',
                            error: responseData.message
                        });
                    }
                }
                else {
                    // 使用原子更新
                    this.Uploads.set(uploadId, {
                        ...currentData,
                        chunksDone: index + 1,
                        progress: ((index + 1) / totalChunks) * 100
                    });

                    this.updateUI();
                }
            }

            // 最终状态检查
            const finalData = this.Uploads.get(uploadId);
            if (finalData) {
                if (controller.signal.aborted) {
                    this.Uploads.set(uploadId, {
                        ...data,
                        status: 'canceled'
                    });
                }
            }
        } catch (error) {
            // 提取错误堆栈中的行号
            const stackLines = error.stack?.split('\n') || [];
            let errorLine = "Unknown";

             // 遍历堆栈的每一行（字符串）
            for (const line of stackLines) {
                // 修正正则表达式，匹配 (文件路径:行号:列号)
                const match = line.match(/[（(](.+?):(\d+):(\d+)[）)]/);
                if (match) {
                    const [_, filePath, lineNum, column] = match;
                    errorLine = `文件: ${filePath}, 行: ${lineNum}`;
                    break;
                }
            }
            // 更新状态为部分失败
            this.Uploads.set(uploadId, {
                ...data,
                status: 'error',
                error: error.message + " in:"+ errorLine
            });
            //console.log(error.message)
        } finally {
            this.updateUI();

            //loadDirectory(currentPath);
        }
    }

    // 关闭弹窗
    closeUploadModal() {
        const modal = document.getElementById('upload-modal');
        modal.style.display = 'none';
    }

    cancelUpload(uploadId) {
        const data = this.Uploads.get(uploadId);
        if (data) {
            data.controller.abort();
            data.status = 'canceled';
            this.updateUI();
        }
    }

    cancelAll() {
        for (const [uploadId, data] of this.Uploads.entries()) {
            data.controller.abort();
            data.status = 'canceled';
        }

        this.updateUI();

        this.closeUploadModal();
    }

    updateUI() {
        const uploadCount = document.getElementById('active-uploads');
        uploadCount.textContent = String(this.Uploads.size);

        const container = document.getElementById('upload-list');
        container.innerHTML = '';

        let activeCount = 0;

        // 事件委托（只需首次绑定）
        if (!this._cancelHandlerBound) {
            container.addEventListener('click', (event) => {
                const cancelBtn = event.target.closest('.cancel-btn');
                if (cancelBtn) {
                    const uploadId = cancelBtn.dataset.id;
                    this.cancelUpload(uploadId);
                }
            });
            this._cancelHandlerBound = true;
        }

        const buttonTextMap = {
            canceled: '已取消',
            error: '重新上传',
            completed: '已完成',
            uploading: '取消上传',
            paused: '继续上传',
            pending: '开始上传'
        };

        const buttonClass = {
            canceled: 'cancel-btn',
            error: 'cancel-btn',
            completed: 'complate-btn',
            uploading: 'cancel-btn',
            paused: 'cancel-btn',
            pending: 'cancel-btn'
        }

        let bAllFinish = true;

        for (const [uploadId, data] of this.Uploads.entries()) {
            //console.log(`ID: ${uploadId}`, `状态: ${data.status}`, `process:${data.progress}`);

            const item = document.createElement('div');
            item.className = 'upload-item';
            item.innerHTML = `
          <div class="file-info">
            <div>${data.file.name}</div>
            <div>${(data.file.size / 1024 / 1024).toFixed(2)} MB</div>
          </div>
          <div class="progress-container">
            <div class="progress-bar" style="width: ${data.progress}%"></div>
            <div class="progress-info">
              <span>${data.chunksDone}/${data.totalChunks} chunks</span>
              <span>${data.progress.toFixed(1)}%</span>
            </div>
          </div>
          <button class="${buttonClass[data.status]}" 
                data-id="${uploadId}"
                    ${['completed', 'canceled'].includes(data.status) ? 'disabled' : ''}>
            ${buttonTextMap[data.status] || '未知状态'}
          </button>
          
          ${data.status === 'error' ?
                    `<div class="error-message">${data.error}</div>` : ''}
        `;
            container.appendChild(item);

            if (['uploading', 'pending'].includes(data.status)) activeCount++;

            if (data.status != "completed") {
                bAllFinish = false;
            }
        }

        const cancelBtn = document.getElementById('cancel-all-button');
        if (bAllFinish) {
            cancelBtn.textContent = '上传完成，点击退出';
            cancelBtn.onclick = OnAllCompQuit;
            cancelBtn.style.backgroundColor = '#44ff6d';
        } else {
            cancelBtn.textContent = '⛔ 停止全部上传';
            cancelBtn.onclick = OnCancelAll;
            cancelBtn.style.backgroundColor = '#ff4444';
        }
    }


    updateDownloadUI() {
        const container = document.getElementById('upload-list');
        container.innerHTML = '';

        let activeCount = 0;

        const buttonTextMap = {
            canceled: '已取消',
            error: '重新下载',
            completed: '已完成',
            Downloading: '取消下载',
            paused: '继续下载',
            pending: '开始下载'
        };

        const buttonClass = {
            canceled: 'cancel-btn',
            error: 'cancel-btn',
            completed: 'complate-btn',
            Downloading: 'cancel-btn',
            paused: 'cancel-btn',
            pending: 'cancel-btn'
        }

        let bAllFinish = true;

        for (const [donwloadId, data] of this.Downloads.entries()) {
            console.log(`ID: ${donwloadId}`, `状态: ${data.status}`);

            const item = document.createElement('div');
            item.className = 'upload-item';
            item.innerHTML = `
          <div class="file-info">
            <div>${data.file.name}</div>
            <div>${(data.file.size / 1024 / 1024).toFixed(2)} MB</div>
          </div>
          <div class="progress-container">
            <div class="progress-bar" style="width: ${data.progress}%"></div>
            <div class="progress-info">
              <span>${data.chunksDone}/${data.totalChunks} chunks</span>
              <span>${data.progress}%</span>
            </div>
          </div>
          <button class="${buttonClass[data.status]}" 
                data-id="${donwloadId}"
                    ${['completed', 'canceled'].includes(data.status) ? 'disabled' : ''}>
            ${buttonTextMap[data.status] || '未知状态'}
          </button>
          
          ${data.status === 'error' ?
                    `<div class="error-message">${data.error}</div>` : ''}
        `;
            container.appendChild(item);

            if (['uploading', 'pending'].includes(data.status)) activeCount++;

            if (data.status != "completed") {
                bAllFinish = false;
            }
        }

        const cancelBtn = document.getElementById('cancel-all-button');
        if (bAllFinish) {
            cancelBtn.textContent = '下载完成，点击退出';
            cancelBtn.onclick = OnAllCompQuit;
            cancelBtn.style.backgroundColor = '#44ff6d';
        } else {
            cancelBtn.textContent = '⛔ 停止全部下载';
            cancelBtn.onclick = OnCancelAll;
            cancelBtn.style.backgroundColor = '#ff4444';
        }
    }

    async getFileSize(filePath, fileName) {
        const response = await fetch('/api/download', { // 替换为实际接口地址
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({
                path: filePath,
                name: fileName,
                method: "getSize" // 触发获取文件大小
            })
        });

        if (!response.ok) throw new Error('获取文件大小失败');
        const data = await response.json();
        return parseInt(data.fileSize); // 返回字节数
    }


    async downloadWithProgress(DownloadID, filePath, fileName) {

        const data = this.Downloads.get(DownloadID);
        if (!data) {
            return;
        }

        data.status = "Downloading";
        this.Downloads.set(DownloadID, data); // 立即更新状态

        // 1. 获取文件大小
        const fileSize = await this.getFileSize(filePath, fileName);

        // 2. 初始化下载
        const response = await fetch('/api/download', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                'Range': `bytes=0-` // 请求整个文件但支持断点
            },
            body: JSON.stringify({ path: filePath, name: fileName })
        });

        // 3. 创建可读流
        const reader = response.body.getReader();
        let received = 0;

        // 4. 实时处理数据
        const chunks = [];
        while (true) {
            // 每次循环前重新获取最新状态
            const currentData = this.Downloads.get(DownloadID);

            // 主动终止条件
            if (!currentData || currentData.status === "Cancelled") {
                console.log("Download cancelled or removed");
                reader.cancel();  // 重要！释放资源
                controller.abort();
                break;
            }


            const { done, value } = await reader.read();
            if (done) break;

            chunks.push(value);
            received += value.length;

            // 更新进度条（示例）
            const progress = (received / fileSize * 100).toFixed(2);
            console.log(`下载进度: ${progress}%`);


            // 使用原子更新
            this.Downloads.set(DownloadID, {
                ...currentData,
                progress: progress
            });

            this.updateDownloadUI();
        }

        // 5. 合并数据并下载
        const fullData = new Uint8Array(received);
        let offset = 0;
        for (const chunk of chunks) {
            fullData.set(chunk, offset);
            offset += chunk.length;
        }

        // 合并数据（建议替换为流式写入）
        const blob = new Blob(chunks);
        const url = URL.createObjectURL(blob);
        const a = document.createElement('a');
        a.href = url;
        a.download = fileName;
        document.body.appendChild(a);
        a.click();
        document.body.removeChild(a);
        setTimeout(() => URL.revokeObjectURL(url), 1000);

        this.Downloads.set(DownloadID, {
            ...data,
            status: "completed",
            progress: 100
        });
        this.updateDownloadUI();
    }

};

// 修改后的上传入口函数
async function chunkedUploadEx(files) {
    if (!files.length) return;

    // 显示上传弹窗
    document.getElementById('upload-modal').style.display = 'block';

    const sessionMgr = new SessionManager();

    sessionControl = sessionMgr;
    // 添加所有文件到上传队列
    Array.from(files).forEach(file => {
        sessionMgr.addUpload(file)
    });
}

async function uploadChunk(file, index, uploadId, totalChunks, chunkSize) {
    const start = index * chunkSize;
    const end = Math.min(file.size, start + chunkSize);
    const chunk = file.slice(start, end);

    const formData = new FormData();
    formData.append('file', chunk);
    formData.append('uploadId', uploadId);
    formData.append('chunkIndex', index);
    formData.append('totalChunks', totalChunks);
    formData.append('filename', file.name);

    try {
        const response = await fetch('/api/upload/chunk', {
            method: 'POST',
            body: formData
        });

        if (!response.ok) throw new Error(`HTTP ${response.status}`);

        console.log(`分片 ${index + 1}/${totalChunks} 上传成功`);
    } catch (error) {
        console.error(`分片 ${index} 上传失败:`, error);
        return false;
    }

    return true;
}


function OnCancelAll() {
    if (sessionControl) {
        sessionControl.cancelAll();
    }

    if (sessionDownload) {
        sessionDownload.closeUploadModal();
    }

    loadDirectory(currentPath);
}

function OnAllCompQuit() {
    if (sessionControl) {
        sessionControl.closeUploadModal();
    }

    if (sessionDownload) {
        sessionDownload.closeUploadModal();
    }

    loadDirectory(currentPath);
}

async function OnDeleteFileList() {
    try {
        // 创建Promise数组（并行执行）
        const deletePromises = Object.keys(checkedState)
            .filter(key => checkedState[key] && checkFile.hasOwnProperty(key))
            .map(async key => {
                const response = await deleteSelf(checkFile[key]);
                return response.json(); // 自动包装为Promise
            });

        // 等待所有删除操作完成
        const results = await Promise.allSettled(deletePromises);

        // 处理操作结果
        results.forEach((result, index) => {
            if (result.status === "fulfilled") {
                console.info(`文件 ${Object.keys(checkedState)[index]} 删除成功:`, result.value);
            } else {
                console.error(`文件 ${Object.keys(checkedState)[index]} 删除失败:`, result.reason);
            }
        });
    } catch (error) {
        console.error("批量删除操作异常:", error);
    } finally {
        // 无论成功失败都刷新目录
        await loadDirectory(currentPath);
        document.getElementById('selectAll').checked = false;
    }
}


async function OnDownloadByList() {
    // 显示上传弹窗
    document.getElementById('upload-modal').style.display = 'block';

    // 创建Promise数组（并行执行）
    const sessionMgr = new SessionManager();
    sessionDownload = sessionMgr;
    Object.keys(checkedState)
        .filter(key => checkedState[key] && checkFile.hasOwnProperty(key))
        .map(async key => {
            if (checkFile[key].name != "") {
                sessionMgr.addDownload(checkFile[key]);
            }
        });
}

function uploadEntrieDir() {
    if (!('webkitdirectory' in document.createElement('input'))) {
        document.getElementById('status').textContent = '当前浏览器不支持文件夹选择';
        return;
    }

    const input = document.createElement('input');
    input.type = 'file';
    input.webkitdirectory = true;
    input.multiple = true;

    input.addEventListener('change', (event) => {
        const files = event.target.files;
        const statusEl = document.getElementById('status');

        if (files.length === 0) {
            statusEl.textContent = '未选择文件夹';
            return;
        }

        try {
            chunkedUploadEx(files);
        } catch (error) {
            console.error('上传流程中断:', error);
            alert(`上传失败: ${error.message}`);
        }


        loadDirectory(currentPath);
    });

    input.click();

}


function removePathPrefix(path, prefix) {
    const formatPath = p => p.replace(/\\/g, '/').toLowerCase();
    const normalizedPath = formatPath(path);
    const normalizedPrefix = formatPath(prefix);
    
    return normalizedPath.startsWith(normalizedPrefix) 
        ? path.slice(prefix.length).replace(/^[/\\]/, '')
        : path;
}

function updatePath(newPath) {

    const result = removePathPrefix(newPath, "FileList");
    
    document.getElementById('current-path').value = "\\" + result;
}

function joinAndNormalizePath(basePath, subPath) {
    // 统一路径分隔符为斜杠
    const unifiedBase = basePath.replace(/\\/g, '/');
    const unifiedSub = subPath.replace(/\\/g, '/');

    // 智能拼接路径
    const combined = [unifiedBase, unifiedSub]
        .join('/') // 安全拼接
        .replace(/\/+/g, '/') // 合并连续斜杠
        .replace(/^\/+|\/+$/g, ''); // 去除首尾多余斜杠

    // 重新添加尾部斜杠（如果需要）
    return combined + (combined.endsWith('/') ? '' : '');
}
